# Deploy a Scalable Web Server Environment Using Terraform ## 学习如何使用 Terraform 部署可扩展、高度可用的 Web 服务器基础架构来提供内容。 ### 任务详情(通过使用AWS CLI) #### 虚拟私有云 (VPC) 创建名为 websrv-vpc 的虚拟私有云。 #### 子网 在您的 VPC 中配置 4 个名为 websrv-vpc 的子网,其中 2 个子网指定为公有子网,2 个指定为私有子网。每对子网(1 个公共子网和 1 个私有子网)必须放置在不同的可用区中,以确保高可用性。 #### 互联网网关 (IGW) 将互联网网关连接到 websrv-vpc,以允许您的 VPC 中的资源访问互联网。 #### NAT 网关 在 websrv-vpc 中部署至少 2 个 NAT 网关,置于不同的可用区,以允许私有子网中的实例访问互联网。 #### 路由表 创建 3 个额外的路由表来管理 websrv-vpc 内的网络流量,包括: 公共路由表,其中包含将互联网流量定向到 IGW 的路由。 每个 AZ 中私有子网的路由表,将互联网绑定流量定向到相应 AZ 的 NAT 网关。 正确的子网关联。公共子网到公共路由表。私有子网到私有路由表。默认主子网不应有关联。 #### 安全组 使用以下规则配置名为 websrv-sg 的安全组: 允许来自任何 IP 地址 (0.0.0.0/0) 的 HTTP 流量(端口 80)的入站规则。 允许所有流量的出站规则,以确保实例可以启动互联网连接。 #### 启动模板 创建名为 websrv-lt 的启动模板。此模板将指定 ASG 将启动的实例的配置。 #### 自动扩展组 (ASG) 使用 websrv-lt 启动模板设置一个名为 websrv-asg 的 ASG。 ASG 必须覆盖至少两个可用区以确保高可用性。 #### 应用程序负载均衡器 (ALB) 部署一个名为 websrv-asg-lb 的 ALB。 ALB 的目的是在由 ASG 管理的实例之间分配传入流量。 #### 目标群体 为 ALB 建立一个名为 websrv-lb-tg 的目标群组。 应将此目标组配置为使用 HTTP 和端口 80,并且必须向其注册 ASG 的实例。 ### 代码参考: ```provider "aws" { region = "us-west-1" # 请根据实际情况选择区域 } resource "aws_vpc" "websrv_vpc" { cidr_block = "10.0.0.0/16" tags = { Name = "websrv-vpc" } } resource "aws_subnet" "public_subnet_1" { vpc_id = aws_vpc.websrv_vpc.id cidr_block = "10.0.1.0/24" availability_zone = "us-west-2a" tags = { Name = "websrv-vpc-public-1" } } resource "aws_subnet" "private_subnet_1" { vpc_id = aws_vpc.websrv_vpc.id cidr_block = "10.0.2.0/24" availability_zone = "us-west-2a" tags = { Name = "websrv-vpc-private-1" } } # 重复上述资源定义,创建第二个可用区的公有和私有子网 resource "aws_internet_gateway" "websrv_igw" { vpc_id = aws_vpc.websrv_vpc.id tags = { Name = "websrv-vpc-igw" } } resource "aws_nat_gateway" "nat_gw_1" { allocation_id = aws_eip.nat_eip_1.id subnet_id = aws_subnet.public_subnet_1.id tags = { Name = "websrv-vpc-nat-gw-1" } } resource "aws_eip" "nat_eip_1" { vpc = true } resource "aws_route_table" "public_rt" { vpc_id = aws_vpc.websrv_vpc.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.websrv_igw.id } tags = { Name = "websrv-vpc-public-rt" } } resource "aws_route_table" "private_rt_1" { vpc_id = aws_vpc.websrv_vpc.id route { cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.nat_gw_1.id } tags = { Name = "websrv-vpc-private-rt-1" } } # 为每个子网关联相应的路由表 resource "aws_route_table_association" "public_subnet_1_assoc" { subnet_id = aws_subnet.public_subnet_1.id route_table_id = aws_route_table.public_rt.id } resource "aws_route_table_association" "private_subnet_1_assoc" { subnet_id = aws_subnet.private_subnet_1.id route_table_id = aws_route_table.private_rt_1.id } resource "aws_security_group" "websrv_sg" { name = "websrv-sg" description = "Allow HTTP traffic and all outbound traffic" vpc_id = aws_vpc.websrv_vpc.id ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_launch_template" "websrv_lt" { name_prefix = "websrv-lt-" image_id = "ami-0c55b159cbfafe1f0" # 请替换为最新的 Amazon Linux 2 AMI ID instance_type = "t2.micro" security_group_ids = [aws_security_group.websrv_sg.id] user_data = <Welcome to the Jam!" > /var/www/html/index.html EOF } resource "aws_autoscaling_group" "websrv_asg" { name = "websrv-asg" launch_template { id = aws_launch_template.websrv_lt.id version = "$Latest" } min_size = 2 max_size = 4 desired_capacity = 2 vpc_zone_identifier = [aws_subnet.private_subnet_1.id, aws_subnet.private_subnet_2.id] # 假设您已经创建了第二个私有子网 target_group_arns = [aws_lb_target_group.websrv_lb_tg.arn] } resource "aws_lb" "websrv_asg_lb" { name = "websrv-asg-lb" internal = false load_balancer_type = "application" security_groups = [aws_security_group.websrv_sg.id] subnets = [aws_subnet.public_subnet_1.id, aws_subnet.public_subnet_2.id] # 假设您已经创建了第二个公有子网 } resource "aws_lb_target_group" "websrv_lb_tg" { name = "websrv-lb-tg" port = 80 protocol = "HTTP" vpc_id = aws_vpc.websrv_vpc.id health_check { path = "/" interval = 30 timeout = 5 healthy_threshold = 5 unhealthy_threshold = 2 } } resource "aws_lb_listener" "http" { load_balancer_arn = aws_lb.websrv_asg_lb.arn port = "80" protocol = "HTTP" default_action { type = "forward" target_group_arn = aws_lb_target_group.websrv_lb_tg.arn } } ```